//
//  TestParticleSystems2.cpp
//  NanoOSX
//
//  Created by Jeppe Nielsen on 9/19/13.
//  Copyright (c) 2013 Jeppe Nielsen. All rights reserved.
//

#include "Engine.hpp"
#include "GameState.hpp"
#include "GameWorld.hpp"
#include "RenderSystem.hpp"
#include "Touchable.hpp"
#include "Material.hpp"
#include "TextureComponent.hpp"
#include "FirstPersonMoverSystem.hpp"
#include "TouchSystem.hpp"
#include "Light.hpp"
#include "SpriteMeshSystem.hpp"
#include "LabelMeshSystem.hpp"
#include "TransformHierarchy.hpp"
#include "SpriteTextureSystem.hpp"
#include "Plane.hpp"
#include "Timer.hpp"
#include "ParticleUpdaterSystem.hpp"
#include "ParticleMeshUpdater.hpp"

using namespace Nano;
using namespace std;

Component(Position)
    Vector3 Position;
};

class TestParticleSystems2 : public GameState<TestParticleSystems2> {
    void Initialize() {
        renderTime = 0;
        renderCounter = 0;
        
        renderer = world.CreateSystem<RenderSystem>();
        world.CreateSystem<FirstPersonMoverSystem>()->Input = &Input;
        world.CreateSystem<ParticleUpdaterSystem>();
        world.CreateSystem<ParticleMeshUpdater>();
        world.CreateSystem<TransformHierarchy>();
        
        // atlas = world.CreateObject();
        // atlas->AddComponent<Atlas>()->Load("images.xml", 1024);
        // atlas->AddComponent<TextureComponent>()->Texture().LoadFromPng("images.png");
        
        
        camera = world.CreateObject();
        cam = camera->AddComponent<Camera>();
        cam->Viewport = Manager().Viewport();
        camera->AddComponent<Transform>()->Position = Vector3(0,0,4);
        camera->AddComponent<FirstPersonMover>();
        
        effect = world.CreateObject();
        ParticleEffect* e = effect->AddComponent<ParticleEffect>();
        e->Duration = 1000;
        e->EmissionFrequency = 0.01f;
        e->EmissionAmount = 2;
        e->Lifetime = { 1.0f, 1.0f };
        
        e->Color.Add(Colour(1.0f,1.0f,1.0f,0.0f), 0);
        e->Color.Add(Colour::White(), 0.1f);
        e->Color.Add(Colour::Yellow(), 0.4f);
        e->Color.Add(Colour::Red(), 0.6f);
        e->Color.Add(Colour::Black(), 0.5f);
        e->Color.Add(Colour(0.0f,0.0f,0.0f,0.0f), 1);
        
        e->Velocity.Add({ Vector3(-4,10,-4), Vector3(4,10,4) }, 0.0f);
        e->Velocity.Add({ Vector3(-4,-10,-4), Vector3(4,10,4) }, 1.0f);
        
        //e->Acceleration.Add(Vector3(0,-30,0), 0.0f);
        
        e->Rotation = { 0, 2 * M_PI };
        e->RotationSpeed.Add(-2.0f * M_PI, 0.0f);
        
        e->Size.Add(0.0f, 0.0f);
        e->Size.Add(1.0f, 0.2f);
        e->Size.Add(1.0f, 0.8f);
        
        GameObject* texture = world.CreateObject();
        texture->AddComponent<TextureComponent>()->Texture().LoadFromPng("smoke2.png");
        
        
        pivot = world.CreateObject();
        pivot->AddComponent<Transform>();
        pivot->AddComponent<Mesh>()->AddCube(0, 1);
        pivot->AddComponent<Material>();
    
        
        cube = world.CreateObject();
        cube->AddComponent<Transform>()->Position = Vector3(10,0,0);
        cube->Parent = pivot;
        cube->AddComponent<Mesh>()->AddCube(0, 1);
        cube->AddComponent<Material>();
        cube->AddComponent<TextureComponent>(texture);
        
        
        emitter = world.CreateObject();
        emitter->AddComponent<ParticleEffect>(effect);
        emitter->AddComponent<ParticleEmitter>()->Playing = true;
        emitter->GetComponent<ParticleEmitter>()->UseWorldSpace = true;
        emitter->AddComponent<Material>()->BlendMode = BlendMode::Add;
        emitter->AddComponent<Mesh>();
        emitter->AddComponent<TextureComponent>(texture);
        emitter->AddComponent<Transform>();
        emitter->GetComponent<Transform>()->Position = Vector3(10,0,0);
        emitter->Parent = pivot;
        
        
        
    }
    
    void Update(float dt) {
        
        Plane plane(Vector3(0,1,0),0);
        
        Ray ray = cam->GetRay(camera->GetComponent<Transform>(), Input.GetTouchPosition(0));
        
        float dist;
        
        if (plane.IntersectsRay(ray, &dist)) {
            //emitter->GetComponent<Transform>()->Position = ray.GetPosition(dist);
        }
        
       
        
        static float rot = 0;
        rot+=dt;
        pivot->GetComponent<Transform>()->Rotation = Quaternion(rot,Vector3(1,1,0).Normalized());
        //emitter->GetComponent<Transform>()->Rotation = Quaternion(-M_PI/2, Vector3(1,0,0));
        world.Update(dt);
    }
    
    void Render() {
        glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glEnable(GL_CULL_FACE);
        renderTimer.Begin();
        renderer->Render();
        renderTime += renderTimer.End();
        renderCounter++;
        if (renderCounter>20) {
            renderTime /= renderCounter;
            cout<<"Render() time = " << (1.0 / renderTime) << endl;
            renderCounter=0;
        }
    }
    
    GameObject* cube;
    GameWorld world;
    RenderSystem* renderer;
    GameObject* effect;
    GameObject* emitter;
    GameObject* atlas;
    GameObject* camera;
    Camera* cam;
    Timer renderTimer;
    double renderTime;
    int renderCounter;
    GameObject* pivot;
};

/*
int main() {
    Engine e;
    e.Start<TestParticleSystems2>();
}
*/






